<template>
	<el-select
			:clearable="_clearable"
			:collapse-tags="_collapseTags"
			:collapse-tags-tooltip="_collapseTagsTooltip"
			:disabled="_disabled"
			:filterable="_filterable"
			:loading="props.loading"
			:loading-text="props.loadingText"
			:multiple="_multiple"
			:placeholder="_placeholder"
			:popper-class="_popperClass"
			class="business-code-select"
			v-bind="$attrs"
			@change="modelValueChanged"
	>
		<template v-for="(value, name) in $slots" #[name]="scope">
			<slot :name="name" v-bind="scope"/>
		</template>
		<el-option v-for="item in options" :key="item.value" :disabled="item.disabled" :label="item.label" :value="item.value"/>
	</el-select>
</template>

<script lang="ts" setup>

import {computed, defineSlots} from 'vue'
import {getBusinessCodeData} from '@/utils/commonUtil'

interface Props {
	codeType: string
	hideValue?: boolean
	loading?: boolean
	loadingText?: string
	disabled?: boolean
	multiple?: boolean
	disabledValueArray?: BusinessCodeTreeNode['value'][]
	hideValueArray?: BusinessCodeTreeNode['value'][]
	placeholder?: string
	popperClass?: string
	clearable?: boolean
	filterable?: boolean
	collapseTags?: boolean
	collapseTagsTooltip?: boolean
	enablePrefix?: boolean
	forceStringValue?: boolean
}

interface OptionItem {
	label: string
	value: BusinessCodeOptionValue
	disabled: boolean
}

const props = withDefaults(defineProps<Props>(), {
	hideValue: true,
	loading: false,
	disabled: false,
	disabledValueArray: () => [],
	hideValueArray: () => [],
	multiple: false,
	placeholder: '请选择',
	clearable: true,
	filterable: true,
	collapseTags: true,
	collapseTagsTooltip: true,
	enablePrefix: false,
	forceStringValue: false
})

defineSlots<{
	default: any
	prefix: any
	empty: any
	header: any
	footer: any
}>()

const emits = defineEmits<{
	(e: 'update:modelValue', value?: BusinessCodeSelectValue): void
	(e: 'change', value?: BusinessCodeSelectValue): void
}>()

const _clearable = computed(() => props.clearable)
const _collapseTags = computed(() => props.collapseTags)
const _collapseTagsTooltip = computed(() => props.collapseTagsTooltip)
const _disabled = computed(() => props.disabled)
const _filterable = computed(() => props.filterable)
const _multiple = computed(() => props.multiple)
const _placeholder = computed(() => props.placeholder)
const _popperClass = computed(() => props.popperClass)

const options = computed<OptionItem[]>(() => {
	const options: OptionItem[] = []
	const businessCodeData = getBusinessCodeData(props.codeType)
	if (businessCodeData && businessCodeData.length > 0) {
		for (const node of businessCodeData) {
			if (props.hideValueArray.includes(node.value)) {
				continue
			}
			options.push({
				label: props.hideValue ? node.label : `${node.value} : ${node.label}`,
				value: handleValue(node.value),
				disabled: props.disabledValueArray.includes(node.value)
			})
		}
	}
	return options
})

const handleValue = (value: string): BusinessCodeOptionValue => {
	if (props.forceStringValue) {
		return value
	}
	// 尝试转换为boolean
	if (value === 'true' || value === 'false') {
		return JSON.parse(value)
	}
	// 尝试转换为number
	const numberValue = Number(value)
	if (Number.isSafeInteger(numberValue)) {
		return numberValue
	}
	// 其他情况使用string
	else {
		return value
	}
}

/**
 * 向父组件传值
 */
const modelValueChanged = (value: BusinessCodeSelectValue) => {
	emits('update:modelValue', value)
	emits('change', value)
}

</script>

<style lang="scss" scoped>
.business-code-select {
	width: 100%;
}
</style>
